const fs = require('fs-extra');
const path = require('path');
const moment = require('moment');

const Excel = require('./../adapter/excel');
const { collectCoverageKind } = require('./../../../project-versions');
const tests = require('./../../../tests');
const BaseReporter = require('./../default-report');

let manualTestsCount = 0;

class DefaultReporter extends BaseReporter {
  /**
   * 生成测试报告总览
   * @param {ProgressIndicator} progressIndicator 进度指示器
   * @returns {Promise}
   */
  generateSummary() {
    if (this.reportRange && this.reportRange.indexOf(1) < 0) {
      return Promise.resolve();
    }
    const summary = {
      reportTime: moment().format('YYYY/MM/DD HH:mm:ss'),
      isIntegrationTest: this.isIntegrationTest(),
      reportName: this.getReportName(),
      coverageRange: !this.version.collectCoverageKind ? collectCoverageKind.all : this.version.collectCoverageKind,
      headerRightContent: `${this.getReportName()} - 总览信息`,
    };
    return this.handleSummary(summary)
      .then(() => Promise.all([
        this.generateCoverageDistributionImage(
          summary.functionsCoverage,
          this.getImageSize().coverageDistributionImage
        ),
        this.generateTestCaseResultsImage(
          summary.testsOverview,
          this.getImageSize().testCaseResultsImage
        ),
        this.generateFunctionResultsImage(
          summary.functionResultsStatistic,
          this.getImageSize().functionResultsImage
        ),
      ]))
      .then(([coverageDistributionImage, testCaseResultsImage, functionResultsImage]) => {
        summary.coverageDistributionImage = coverageDistributionImage.output;
        summary.testCaseResultsImage = testCaseResultsImage.output;
        summary.functionResultsImage = functionResultsImage.output;
        return this.generateSummaryReport(
          summary,
          path.join(
            this.outputDir,
            this.project.projectName,
            this.version.versionName,
            'summary'
          )
        )
          .then(() => this.generateXlsxSummary(
            summary,
            path.join(
              this.outputDir,
              this.project.projectName,
              this.version.versionName,
              'summary'
            )
          ))
          .then(() => {
            fs.remove(coverageDistributionImage.output);
            fs.remove(testCaseResultsImage.output);
            fs.remove(functionResultsImage.output);
          });
      });
  }

  generateXlsxSummary(summary, reportPath) {
    const excel = new Excel(this.creator.username);
    const font = { name: 'Times New Roman', size: 11 };
    const border = {
      top: { style: 'thin' },
      left: { style: 'thin' },
      right: { style: 'thin' },
      bottom: { style: 'thin' },
    };
    excel.addSheet('总览');
    excel.setColumn('A', { width: 22 });
    excel.setColumn('B', { width: 22 });
    excel.setColumn('C', { width: 22 });
    excel.setCell('A1', { value: '项目名称', font, border });
    excel.setCell('B1', { value: summary.overview.projectName, font, border });
    excel.mergeCells('B1', 'C1');
    excel.setCell('A2', { value: '版本号', font, border });
    excel.setCell('B2', { value: summary.overview.versionName, font, border });
    excel.mergeCells('B2', 'C2');
    excel.setCell('A3', { value: '日期', font, border });
    excel.setCell('B3', { value: summary.reportTime, font, border });
    excel.mergeCells('B3', 'C3');
    excel.setCell('A4', { value: '测试概况\n（测试对象统计）', font, border });
    excel.mergeCells('A4', 'A10');
    excel.setCell('B4', { value: '源文件（个）', font, border });
    excel.setCell('C4', { value: summary.overview.sourceFileCount, font, border });
    excel.setCell('B5', { value: '头文件（个）', font, border });
    excel.setCell('C5', { value: summary.overview.headerFileCount, font, border });
    excel.setCell('B6', { value: '函数（个）', font, border });
    excel.setCell('C6', { value: summary.overview.functionCount, font, border });
    excel.setCell('B7', { value: '函数通过数（个）', font, border });
    excel.setCell('C7', { value: summary.functionResultsStatistic.passed, font, border });
    excel.setCell('B8', { value: '代码行数', font, border });
    excel.mergeCells('B8', 'B10');
    excel.setCell('C8', { value: `总行数：${summary.overview.numberOfLines}`, font, border });
    excel.setCell('C9', { value: `源文件行数：${summary.overview.sourceNumberOfLines}`, font, border });
    excel.setCell('C10', { value: `头文件行数：${summary.overview.headerNumberOfLines}`, font, border });
    excel.setCell('A11', { value: '覆盖概况\n（测试对象统计）', font, border });
    excel.mergeCells('A11', `A${summary.enabledCoverageKind.length * 2 + 10}`);
    summary.enabledCoverageKind.forEach((c, idx) => {
      excel.setCell(`B${11 + idx * 2}`, { value: summary.enabledCoverageKind[idx].name, font, border });
      excel.mergeCells(`B${11 + idx * 2}`, `B${12 + idx * 2}`);
      excel.setCell(`C${11 + idx * 2}`, { value: summary.overview[summary.enabledCoverageKind[idx].coverageKey], font, border });
      excel.setCell(`C${12 + idx * 2}`, { value: `${summary.overview[summary.enabledCoverageKind[idx].coveredKey]}/${summary.overview[summary.enabledCoverageKind[idx].totalKey]}`, font, border });
    });
    excel.setCell(`A${summary.enabledCoverageKind.length * 2 + 11}`, { value: '用例概况\n（测试对象统计）', font, border });
    excel.mergeCells(`A${summary.enabledCoverageKind.length * 2 + 11}`, `A${summary.enabledCoverageKind.length * 2 + 20}`);
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 11}`, { value: '用例总数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 11}`, { value: summary.testsOverview.total, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 12}`, { value: '自动生成用例数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 12}`, { value: summary.testsOverview.total - manualTestsCount, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 13}`, { value: '手动添加用例数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 13}`, { value: manualTestsCount, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 14}`, { value: '执行数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 14}`, { value: summary.testsOverview.total - summary.testsOverview.unknown, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 15}`, { value: '执行通过数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 15}`, { value: summary.testsOverview.succeed + summary.testsOverview.nonStrictSucceed, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 16}`, { value: '执行未通过数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 16}`, { value: summary.testsOverview.failed, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 17}`, { value: '执行异常数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 17}`, { value: summary.testsOverview.exception, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 18}`, { value: '运行时错误数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 18}`, { value: summary.testsOverview.codeDefect, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 19}`, { value: '无结果数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 19}`, { value: summary.testsOverview.noResult, font, border });
    excel.setCell(`B${summary.enabledCoverageKind.length * 2 + 20}`, { value: '未执行数', font, border });
    excel.setCell(`C${summary.enabledCoverageKind.length * 2 + 20}`, { value: summary.testsOverview.unknown, font, border });
    return excel.writeFile(`${reportPath}.xlsx`);
  }

  getFunctionDetailsOfFile(typeSystem, functions) {
    const resFunctions = [];
    functions.sort((a, b) => {
      if (a.index < b.index) return -1;
      if (a.index > b.index) return 1;
      return 0;
    });
    functions.forEach((func) => {
      if (!func.tests.length) {
        return;
      }
      func.tests.forEach((t) => {
        if (t.kind === tests.testKind.modified) {
          manualTestsCount += 1;
        }
      });
      resFunctions.push({
        functionName: func.functionName,
        description: func.description,
        udfs: func.udfs,
        codeDefects: this.getCodeDefects(func),
        // to be modified
        summary: this.getSummaryOfFunction(func),
        tests: this.getTestDetailsOfFunction(typeSystem, func),
        integrationFunctions: func.integrationFunctions,
        integrationFunctionsCount: func.integrationFunctions.length,
      });
    });
    return resFunctions;
  }

  // eslint-disable-next-line no-unused-vars
  static versionTypeSupport(vType) {
    return true;
  }
}

/**
 * Export model definition object.
 */
module.exports = DefaultReporter;
